const configData = {
  baudRate: 9600,
  dataBits: 8,
  parity: 'none' as const,
  stopBits: 1,
  flowControl: 'none' as const,
}

const isAndroid = (): boolean => typeof navigator !== 'undefined' && /Android/i.test(navigator.userAgent)

const supportsSerialAPI = (): boolean => typeof navigator !== 'undefined' && 'serial' in navigator

export const SerialCommunicator = {
  port: null as any,
  reader: null as any,
  isConnected: false,
  isReading: false,
  websocket: null as WebSocket | null,
  stats: { sent: 0, received: 0 },
  reconnectAttempts: 0,
  maxReconnectAttempts: 5,

  async connect(socket: WebSocket) {
    this.websocket = socket
    try {
      // if (!supportsSerialAPI()) {
      //   const errorMsg = isAndroid() ? '安卓浏览器不支持串口通信，请用最新版Chrome' : '浏览器不支持串口API，请用Chrome/Edge等'
      //   throw new Error(errorMsg)
      // }
      // if (isAndroid()) {
      //   uni.showToast({
      //     title: '请选择串口设备',
      //     icon: 'none',
      //     duration: 2000,
      //   })
      // }
      this.port = await navigator.serial.requestPort()
      const openOptions = {
        ...configData,
        bufferSize: isAndroid() ? 8192 : 1024,
      }
      await this.port.open(openOptions)
      this.isConnected = true
      this.reconnectAttempts = 0
      this.startReading()
      return true
    } catch (error: any) {
      let errorMsg = error.message
      if (isAndroid()) {
        if (error.message.includes('Permission denied')) errorMsg = '请授予串口权限'
        else if (error.message.includes('NotFoundError')) errorMsg = '未找到串口设备'
      }
      uni.showToast({ title: errorMsg, icon: 'none', duration: 2000 })
      this.isConnected = false
      return false
    }
  },

  async startReading() {
    if (!this.port || !this.port.readable || this.isReading) return
    this.isReading = true
    this.isConnected = true
    const readLoop = async () => {
      while (this.port?.readable && this.isConnected && this.isReading) {
        try {
          this.reader = this.port.readable.getReader()
          const { value, done } = await this.reader.read()
          if (done) break
          if (value) {
            this.stats.received++
            if (this.websocket && this.websocket.readyState === WebSocket.OPEN) {
              const deviceId = uni.getStorageSync('deviceId') || ''
              const hexString = Array.from(value)
                .map((b: any) => b.toString(16).padStart(2, '0'))
                .join('')
              this.websocket.send(`HDALLCXX${deviceId}CXX${hexString}`)
            }
          }
        } catch (err: any) {
          if (isAndroid() && err.name !== 'AbortError') {
            if (this.reconnectAttempts < this.maxReconnectAttempts) {
              this.reconnectAttempts++
              await this.reconnect()
              break
            } else {
              uni.showToast({ title: '多次尝试后仍无法读取', icon: 'none', duration: 2000 })
              this.disconnect()
            }
          } else if (err.name !== 'AbortError') {
            uni.showToast({ title: `读取错误: ${err.message}`, icon: 'none', duration: 2000 })
          }
        } finally {
          if (this.reader) {
            await this.reader.releaseLock().catch(() => {})
            this.reader = null
          }
        }
      }
      this.isReading = false
      if (this.isConnected) setTimeout(() => this.startReading(), 1000)
    }
    readLoop()
  },

  handleWebSocketError() {
    if (!this.websocket) return
    this.websocket.close()
    if (isAndroid() && this.isConnected) {
      setTimeout(() => {
        uni.showToast({ title: '需要重新连接WebSocket' })
      }, 1000)
    }
  },

  async reconnect() {
    try {
      if (this.reader) {
        await this.reader.cancel().catch(() => {})
        this.reader = null
      }
      if (this.port) {
        await this.port.close().catch(() => {})
        await this.port.open(configData)
        uni.showToast({ title: `重连成功 (${this.reconnectAttempts})`, icon: 'none', duration: 1500 })
        this.startReading()
        return true
      }
      return false
    } catch {
      return false
    }
  },

  async disconnect() {
    this.isConnected = false
    this.isReading = false
    if (this.reader) {
      try {
        await this.reader.cancel()
      } catch {}
      this.reader = null
    }
    if (this.port) {
      try {
        await this.port.close()
      } catch {}
      this.port = null
    }
    this.stats = { sent: 0, received: 0 }
  },

  async sendData(data: Uint8Array) {
    if (!this.port || !this.port.writable || !this.isConnected) {
      throw new Error('串口未连接或不可写')
    }
    try {
      const writer = this.port.writable.getWriter()
      if (isAndroid()) {
        const chunkSize = 64
        for (let i = 0; i < data.length; i += chunkSize) {
          const chunk = data.subarray(i, i + chunkSize)
          await writer.write(chunk)
          await new Promise((resolve) => setTimeout(resolve, 10))
        }
      } else {
        await writer.write(data)
      }
      this.stats.sent++
      await writer.releaseLock()
      return true
    } catch (error: any) {
      if (isAndroid()) {
        uni.showToast({ title: '发送失败，尝试重连', icon: 'none', duration: 2000 })
        this.reconnect()
      }
      throw error
    }
  },
}
